﻿Imports System.Data
Imports Microsoft.VisualBasic
Imports System.Security.Principal
Imports System.Security.Cryptography

Public Class clsImpersonate
#Region "VARIABLES Y DECLARACIONES NECESARIAS"
    Dim LOGON32_LOGON_INTERACTIVE As Integer = 2
    Dim LOGON32_PROVIDER_DEFAULT As Integer = 0
    Dim impersonationContext As WindowsImpersonationContext
    Declare Function LogonUserA Lib "advapi32.dll" (ByVal lpszUsername As String, ByVal lpszDomain As String, ByVal lpszPassword As String, ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, ByRef phToken As IntPtr) As Integer
    Declare Auto Function DuplicateToken Lib "advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, ByVal ImpersonationLevel As Integer, ByRef DuplicateTokenHandle As IntPtr) As Integer
    Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
    Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
#End Region

#Region "Declaración de Propiedades"
    Private clsDominio As String
    Private clsUsuario As String
    Private clsPassword As String
    Private clsImpersonalizo As Boolean
    Private clsErrorMessage As String
#End Region

#Region "CONSTRUCTOR"
    ''' <summary>
    ''' Constructor para impersonalizar
    ''' </summary>
    ''' <param name="Dominio">Dominio de Usuario a Ocupar</param>
    ''' <param name="Usuario">Nombre de Usuario a Ocupar</param>
    ''' <param name="Password">Password de Usuario a ocupar</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal Dominio As String, ByVal Usuario As String, ByVal Password As String)
        Me.clsDominio = Dominio
        Me.clsUsuario = Usuario
        Me.clsPassword = Password
        Me.clsImpersonalizo = False
        Me.clsErrorMessage = ""
    End Sub
#End Region

#Region "Metodos de Acceso A Propiedades"
    ''' <summary>
    ''' devuelve si la impersonalizacion fue correcta o no
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property Impersonalizo() As Boolean
        Get
            Return Me.clsImpersonalizo
        End Get
    End Property

    ''' <summary>
    ''' devuelve el mensaje con el error producido en caso de
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property MensajeError() As String
        Get
            Return Me.clsErrorMessage
        End Get
    End Property
#End Region

#Region "EVENTOS DE LA CLASE"
    ''' <summary>
    ''' Valida la impersonalización
    ''' </summary>
    ''' <param name="Impersonalizar"></param>
    ''' <remarks></remarks>
    Public Sub impersonateValidUser(Optional ByVal Impersonalizar As Boolean = True)
        Me.clsImpersonalizo = False
        Me.clsErrorMessage = ""

        If Impersonalizar = False Then
            Me.clsImpersonalizo = True
            Exit Sub
        End If

        Try
            Dim tempWindowsIdentity As WindowsIdentity
            Dim token As IntPtr = IntPtr.Zero
            Dim tokenDuplicate As IntPtr = IntPtr.Zero

            If RevertToSelf() Then
                If LogonUserA(Me.clsUsuario, Me.clsDominio, Me.clsPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
                    If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
                        tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
                        impersonationContext = tempWindowsIdentity.Impersonate()
                        If Not impersonationContext Is Nothing Then
                            Me.clsImpersonalizo = True
                        End If
                    End If
                End If
            End If
            If Not tokenDuplicate.Equals(IntPtr.Zero) Then
                CloseHandle(tokenDuplicate)
            End If
            If Not token.Equals(IntPtr.Zero) Then
                CloseHandle(token)
            End If
        Catch ex As Exception
            Me.clsErrorMessage = ex.Message.ToString
        End Try
    End Sub

    ''' <summary>
    ''' Quita la impersonalización configurada
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub undoImpersonation()
        Try
            impersonationContext.Undo()
            Me.clsImpersonalizo = False
            Me.clsErrorMessage = ""
        Catch ex As Exception
            Me.clsErrorMessage = ex.Message.ToString
        End Try
    End Sub

    ''' <summary>
    ''' Elimina el objeto de memoria
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub Dispose()
        Try
            Call undoImpersonation()
            GC.SuppressFinalize(Me)
        Catch ex As Exception
        End Try
    End Sub
#End Region
End Class
